﻿//--------------------------------------------------------------------------
// 
//  Copyright (c) Chili Software.  All rights reserved. 
// 
//  File: ICustomPersister.cs
//
//  Description: Interface that allows to control the persist and load.
// 
//--------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using Chili.Opf3.Query;

namespace Chili.Opf3
{
	/// <summary>
	/// This interface is implemented by classes that want do their save and load in a special mode.
	/// </summary>
	/// <remarks>
	/// <para>
	/// A class that needs a special way to persist or to load its member from the storage has to 
	/// implement this interface. It's recommended to use this interface only for complex classes, that means
	/// classes consisting of a few or a list of persistent objects.
	/// If the <see cref="Opf3.ObjectContext">ObjectContext</see> encounters a class that implements
	/// this interface the load process (or persist process) is directly passed to the class. The class
	/// can then do it's special way to load or persist the members. As argument is passed 
	/// the <see cref="Opf3.ObjectContext">ObjectContext</see> that should be used to load (or persist) the
	/// changes on the objects.
	/// </para>
	/// <para>
	/// Currently <see cref="Opf3.ObjectSet{T}">ObjectSet</see> implements this interface to do the 
	/// custom save process. <see cref="Opf3.ObjectSet{T}">ObjectSet</see>
	/// uses this interface since it has to save all persistent objects in the main list and to delete 
	/// all persistent objects in the <see cref="Opf3.ObjectSet{T}.RemovedList">RemovedList</see>. 
	/// Without implementing this interface the user would have to delete manually the objects in the 
	/// <see cref="Opf3.ObjectSet{T}.RemovedList">RemovedList</see>.
	/// </para>
	/// </remarks>
	/// <example>
	/// The following example shows a sample implementation of the interface.
	/// <code lang="CS">
	/// public class MyList&lt;T&gt; : ICustomPersister&lt;T:gt;
	/// {
	///		private IList&lt;T&gt; _removedList = new List&lt;T&gt;();
	/// 
	///		public void Load(ObjectContext context, IQuery query)
	///		{
	///			// Load all objects matching the query.
	///			using(ObjectReader&lt;T&gt; reader = 
	///				context.GetObjectReader&lt;T&gt;(query))
	///			{
	///				// Add all objects found to the list.
	///				foreach(T obj in reader)
	///					this.Add(obj);
	///			}
	///		}
	/// 
	///		public void Persist(ObjectContext context, PersistDepths persistDepth, PersistingTrace trace)
	///		{
	///			foreach (T obj in this)
	///				context.PersistChanges&lt;T&gt;(obj, persistDepth);
	///
	///			// Delete all objects in the RemovedList.
	///			foreach (T obj in _removedList)
	///			{
	///				context.MarkForDeletion(obj);
	///				context.PersistChanges&lt;T&gt;(obj, persistDepth);
	///			}
	///			_removedList.Clear();
	///		}
	/// 
	///		public void MoveToRemovedList(T obj)
	///		{
	///			this.Remove(obj);
	///			_removedList.Add(obj);
	///		}
	/// 
	///		// ... Other properties and code.
	/// }
	/// </code>
	/// </example>
	public interface ICustomPersister
	{
		/// <summary>
		/// This method is called during load from the storage by the <see cref="Opf3.ObjectContext">ObjectContext</see> 
		/// class.
		/// </summary>
		/// <param name="context"><see cref="Opf3.ObjectContext">ObjectContext</see> that called this routine.</param>
		/// <param name="query"><see cref="Opf3.Query.IQuery">IQuery</see> that is executed by the context to 
		/// load the objects.</param>
		void Load(ObjectContext context, IQuery query);

		/// <summary>
		/// This method is called during load from the storage by the <see cref="Opf3.ObjectContext">ObjectContext</see> 
		/// class.
		/// </summary>
		/// <param name="context"><see cref="Opf3.ObjectContext">ObjectContext</see> that called this routine.</param>
		/// <param name="query"><see cref="Opf3.Query.IQuery">IQuery</see> that is executed by the context to 
		/// load the objects.</param>
		/// <param name="amount">Specifies the maximum amount of objects that have to be loaded from the storage.</param>
		void Load(ObjectContext context, IQuery query, int amount);

		/// <summary>
		/// <para>
		/// This routine is called by the <see cref="Opf3.ObjectContext">ObjectContext</see>
		/// during save operations on the storage.
		/// </para>
		/// <para>
		/// <b>Attention:</b> The <see cref="ICustomPersister">ICustomPersister</see> should only add an object 
		/// to the <see cref="PersistingTrace">PersistingTrace</see> (see the argument) if not
		/// using the <see cref="ObjectContext">ObjectContext</see> to save its persistent objects.
		/// </para>
		/// </summary>
		/// <param name="context"><see cref="Opf3.ObjectContext">ObjectContext</see> that called this routine.</param>
		/// <param name="persistDepth">Specifies the depth of the object graph that is persisted.</param>
		/// <param name="persistingTrace">Contains information about the recently persistet objects. The 
		/// <see cref="ICustomPersister">ICustomPersister</see> should only add an object to this trace if not
		/// using the <see cref="ObjectContext">ObjectContext</see> to save its persistent objects.</param>
		void Persist(ObjectContext context, PersistDepths persistDepth, PersistingTrace persistingTrace);
	}
}
